home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / vidhrdw / shuuz.c < prev    next >
C/C++ Source or Header  |  2000-04-04  |  18KB  |  631 lines

  1. /***************************************************************************
  2.  
  3.   vidhrdw/shuuz.c
  4.  
  5.   Functions to emulate the video hardware of the machine.
  6.  
  7. ****************************************************************************
  8.  
  9.     Playfield encoding
  10.     ------------------
  11.         1 16-bit word is used
  12.  
  13.         Word 1:
  14.             Bits 13-15 = palette
  15.             Bits  0-12 = image number
  16.  
  17.  
  18.     Motion Object encoding
  19.     ----------------------
  20.         4 16-bit words are used
  21.  
  22.         Word 1:
  23.             Bits  0-7  = link to the next motion object
  24.  
  25.         Word 2:
  26.             Bits  0-11 = image index
  27.  
  28.         Word 3:
  29.             Bits  7-15 = horizontal position
  30.             Bits  0-3  = motion object palette
  31.  
  32.         Word 4:
  33.             Bits  7-15 = vertical position
  34.             Bits  4-6  = horizontal size of the object, in tiles
  35.             Bit   3    = horizontal flip
  36.             Bits  0-2  = vertical size of the object, in tiles
  37.  
  38. ***************************************************************************/
  39.  
  40. #include "driver.h"
  41. #include "machine/atarigen.h"
  42. #include "vidhrdw/generic.h"
  43.  
  44. #define XCHARS 42
  45. #define YCHARS 30
  46.  
  47. #define XDIM (XCHARS*8)
  48. #define YDIM (YCHARS*8)
  49.  
  50.  
  51. #define DEBUG_VIDEO 0
  52.  
  53.  
  54.  
  55. /*************************************
  56.  *
  57.  *    Constants
  58.  *
  59.  *************************************/
  60.  
  61. #define OVERRENDER_STANDARD        0
  62. #define OVERRENDER_PRIORITY        1
  63.  
  64.  
  65.  
  66. /*************************************
  67.  *
  68.  *    Structures
  69.  *
  70.  *************************************/
  71.  
  72. struct pf_overrender_data
  73. {
  74.     struct osd_bitmap *bitmap;
  75.     int type, color;
  76. };
  77.  
  78.  
  79.  
  80. /*************************************
  81.  *
  82.  *    Statics
  83.  *
  84.  *************************************/
  85.  
  86. #if DEBUG_VIDEO
  87. static UINT8 show_colors;
  88. #endif
  89.  
  90.  
  91.  
  92. /*************************************
  93.  *
  94.  *    Prototypes
  95.  *
  96.  *************************************/
  97.  
  98. static const UINT8 *update_palette(void);
  99.  
  100. static void pf_color_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *data);
  101. static void pf_render_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *data);
  102. static void pf_overrender_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *data);
  103.  
  104. static void mo_color_callback(const UINT16 *data, const struct rectangle *clip, void *param);
  105. static void mo_render_callback(const UINT16 *data, const struct rectangle *clip, void *param);
  106.  
  107. #if DEBUG_VIDEO
  108. static void debug(void);
  109. #endif
  110.  
  111.  
  112.  
  113. /*************************************
  114.  *
  115.  *    Video system start
  116.  *
  117.  *************************************/
  118.  
  119. int shuuz_vh_start(void)
  120. {
  121.     static struct atarigen_mo_desc mo_desc =
  122.     {
  123.         256,                 /* maximum number of MO's */
  124.         8,                   /* number of bytes per MO entry */
  125.         2,                   /* number of bytes between MO words */
  126.         0,                   /* ignore an entry if this word == 0xffff */
  127.         0, 0, 0xff,          /* link = (data[linkword] >> linkshift) & linkmask */
  128.         0                    /* render in reverse link order */
  129.     };
  130.  
  131.     static struct atarigen_pf_desc pf_desc =
  132.     {
  133.         8, 8,                /* width/height of each tile */
  134.         64, 64,                /* number of tiles in each direction */
  135.         1                    /* non-scrolling */
  136.     };
  137.  
  138.     /* initialize the playfield */
  139.     if (atarigen_pf_init(&pf_desc))
  140.         return 1;
  141.  
  142.     /* initialize the motion objects */
  143.     if (atarigen_mo_init(&mo_desc))
  144.     {
  145.         atarigen_pf_free();
  146.         return 1;
  147.     }
  148.  
  149.     return 0;
  150. }
  151.  
  152.  
  153.  
  154. /*************************************
  155.  *
  156.  *    Video system shutdown
  157.  *
  158.  *************************************/
  159.  
  160. void shuuz_vh_stop(void)
  161. {
  162.     atarigen_pf_free();
  163.     atarigen_mo_free();
  164. }
  165.  
  166.  
  167.  
  168. /*************************************
  169.  *
  170.  *    Playfield RAM write handler
  171.  *
  172.  *************************************/
  173.  
  174. WRITE_HANDLER( shuuz_playfieldram_w )
  175. {
  176.     int oldword = READ_WORD(&atarigen_playfieldram[offset]);
  177.     int newword = COMBINE_WORD(oldword, data);
  178.  
  179.     /* update the data if different */
  180.     if (oldword != newword)
  181.     {
  182.         WRITE_WORD(&atarigen_playfieldram[offset], newword);
  183.         atarigen_pf_dirty[(offset & 0x1fff) / 2] = 1;
  184.     }
  185.  
  186.     /* handle the latch, but only write the upper byte */
  187.     if (offset < 0x2000 && atarigen_video_control_state.latch1 != -1)
  188.         shuuz_playfieldram_w(offset + 0x2000, atarigen_video_control_state.latch1 | 0x00ff0000);
  189. }
  190.  
  191.  
  192.  
  193. /*************************************
  194.  *
  195.  *    Periodic scanline updater
  196.  *
  197.  *************************************/
  198.  
  199. void shuuz_scanline_update(int scanline)
  200. {
  201.     /* update the playfield */
  202.     if (scanline == 0)
  203.         atarigen_video_control_update(&atarigen_playfieldram[0x1f00]);
  204.  
  205.     /* update the MOs from the SLIP table */
  206.     atarigen_mo_update_slip_512(atarigen_spriteram, atarigen_video_control_state.sprite_yscroll, scanline, &atarigen_playfieldram[0x1f80]);
  207. }
  208.  
  209.  
  210.  
  211. /*************************************
  212.  *
  213.  *    Main refresh
  214.  *
  215.  *************************************/
  216.  
  217. void shuuz_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
  218. {
  219. #if DEBUG_VIDEO
  220.     debug();
  221. #endif
  222.  
  223.     /* remap if necessary */
  224.     if (update_palette())
  225.         memset(atarigen_pf_dirty, 1, atarigen_playfieldram_size / 4);
  226.  
  227.     /* update playfield */
  228.     atarigen_pf_process(pf_render_callback, bitmap, &Machine->drv->visible_area);
  229.  
  230.     /* render the motion objects */
  231.     atarigen_mo_process(mo_render_callback, bitmap);
  232.  
  233.     /* update onscreen messages */
  234.     atarigen_update_messages();
  235. }
  236.  
  237.  
  238.  
  239. /*************************************
  240.  *
  241.  *    Palette management
  242.  *
  243.  *************************************/
  244.  
  245. static const UINT8 *update_palette(void)
  246. {
  247.     UINT16 mo_map[16], pf_map[16];
  248.     int i, j;
  249.  
  250.     /* reset color tracking */
  251.     memset(mo_map, 0, sizeof(mo_map));
  252.     memset(pf_map, 0, sizeof(pf_map));
  253.     palette_init_used_colors();
  254.  
  255.     /* update color usage for the playfield */
  256.     atarigen_pf_process(pf_color_callback, pf_map, &Machine->drv->visible_area);
  257.  
  258.     /* update color usage for the mo's */
  259.     atarigen_mo_process(mo_color_callback, mo_map);
  260.  
  261.     /* rebuild the playfield palette */
  262.     for (i = 0; i < 16; i++)
  263.     {
  264.         UINT16 used = pf_map[i];
  265.         if (used)
  266.             for (j = 0; j < 16; j++)
  267.                 if (used & (1 << j))
  268.                     palette_used_colors[0x100 + i * 16 + j] = PALETTE_COLOR_USED;
  269.     }
  270.  
  271.     /* rebuild the motion object palette */
  272.     for (i = 0; i < 16; i++)
  273.     {
  274.         UINT16 used = mo_map[i];
  275.         if (used)
  276.         {
  277.             palette_used_colors[0x000 + i * 16 + 0] = PALETTE_COLOR_TRANSPARENT;
  278.             for (j = 1; j < 16; j++)
  279.                 if (used & (1 << j))
  280.                     palette_used_colors[0x000 + i * 16 + j] = PALETTE_COLOR_USED;
  281.         }
  282.     }
  283.  
  284.     /* special case color 15 of motion object palette 15 */
  285.     palette_used_colors[0x000 + 15 * 16 + 15] = PALETTE_COLOR_TRANSPARENT;
  286.  
  287.     return palette_recalc();
  288. }
  289.  
  290.  
  291.  
  292. /*************************************
  293.  *
  294.  *    Playfield palette
  295.  *
  296.  *************************************/
  297.  
  298. static void pf_color_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  299. {
  300.     const unsigned int *usage = Machine->gfx[0]->pen_usage;
  301.     UINT16 *colormap = param;
  302.     int x, y;
  303.  
  304.     /* standard loop over tiles */
  305.     for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 63)
  306.         for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  307.         {
  308.             int offs = x * 64 + y;
  309.             int data1 = READ_WORD(&atarigen_playfieldram[offs * 2]);
  310.             int data2 = READ_WORD(&atarigen_playfieldram[offs * 2 + 0x2000]);
  311.             int code = data1 & 0x3fff;
  312.             int color = (data2 >> 8) & 15;
  313.  
  314.             /* mark the colors used by this tile */
  315.             colormap[color] |= usage[code];
  316.         }
  317. }
  318.  
  319.  
  320.  
  321. /*************************************
  322.  *
  323.  *    Playfield rendering
  324.  *
  325.  *************************************/
  326.  
  327. static void pf_render_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  328. {
  329.     const struct GfxElement *gfx = Machine->gfx[0];
  330.     struct osd_bitmap *bitmap = param;
  331.     int x, y;
  332.  
  333.     /* standard loop over tiles */
  334.     for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 63)
  335.         for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  336.         {
  337.             int offs = x * 64 + y;
  338.  
  339.             /* update only if dirty */
  340.             if (atarigen_pf_dirty[offs])
  341.             {
  342.                 int data1 = READ_WORD(&atarigen_playfieldram[offs * 2]);
  343.                 int data2 = READ_WORD(&atarigen_playfieldram[offs * 2 + 0x2000]);
  344.                 int color = (data2 >> 8) & 15;
  345.                 int hflip = data1 & 0x8000;
  346.                 int code = data1 & 0x3fff;
  347.  
  348.                 drawgfx(atarigen_pf_bitmap, gfx, code, color, hflip, 0, 8 * x, 8 * y, 0, TRANSPARENCY_NONE, 0);
  349.                 atarigen_pf_dirty[offs] = 0;
  350.  
  351. #if DEBUG_VIDEO
  352.                 if (show_colors)
  353.                 {
  354.                     drawgfx(atarigen_pf_bitmap, Machine->uifont, "0123456789ABCDEF"[color], 1, 0, 0, 8 * x + 0, 8 * y, 0, TRANSPARENCY_PEN, 0);
  355.                     drawgfx(atarigen_pf_bitmap, Machine->uifont, "0123456789ABCDEF"[color], 1, 0, 0, 8 * x + 2, 8 * y, 0, TRANSPARENCY_PEN, 0);
  356.                     drawgfx(atarigen_pf_bitmap, Machine->uifont, "0123456789ABCDEF"[color], 0, 0, 0, 8 * x + 1, 8 * y, 0, TRANSPARENCY_PEN, 0);
  357.                 }
  358. #endif
  359.             }
  360.         }
  361.  
  362.     /* then blast the result */
  363.     copybitmap(bitmap, atarigen_pf_bitmap, 0, 0, 0, 0, clip, TRANSPARENCY_NONE, 0);
  364. }
  365.  
  366.  
  367.  
  368. /*************************************
  369.  *
  370.  *    Playfield overrendering
  371.  *
  372.  *************************************/
  373.  
  374. static void pf_overrender_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  375. {
  376.     const struct pf_overrender_data *overrender_data = param;
  377.     const struct GfxElement *gfx = Machine->gfx[0];
  378.     struct osd_bitmap *bitmap = overrender_data->bitmap;
  379.     int x, y;
  380.  
  381.     /* standard loop over tiles */
  382.     for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 63)
  383.         for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  384.         {
  385.             int offs = x * 64 + y;
  386.             int data2 = READ_WORD(&atarigen_playfieldram[offs * 2 + 0x2000]);
  387.             int color = (data2 >> 8) & 15;
  388.  
  389.             /* overdraw if the color is 15 */
  390.             if (((color & 8) && color >= overrender_data->color) || overrender_data->type == OVERRENDER_PRIORITY)
  391.             {
  392.                 int data1 = READ_WORD(&atarigen_playfieldram[offs * 2]);
  393.                 int hflip = data1 & 0x8000;
  394.                 int code = data1 & 0x3fff;
  395.  
  396.                 drawgfx(bitmap, gfx, code, color, hflip, 0, 8 * x, 8 * y, clip, TRANSPARENCY_NONE, 0);
  397.  
  398. #if DEBUG_VIDEO
  399.                 if (show_colors)
  400.                 {
  401.                     drawgfx(bitmap, Machine->uifont, "0123456789ABCDEF"[color], 1, 0, 0, 8 * x + 0, 8 * y, 0, TRANSPARENCY_PEN, 0);
  402.                     drawgfx(bitmap, Machine->uifont, "0123456789ABCDEF"[color], 1, 0, 0, 8 * x + 2, 8 * y, 0, TRANSPARENCY_PEN, 0);
  403.                     drawgfx(bitmap, Machine->uifont, "0123456789ABCDEF"[color], 0, 0, 0, 8 * x + 1, 8 * y, 0, TRANSPARENCY_PEN, 0);
  404.                 }
  405. #endif
  406.             }
  407.         }
  408. }
  409.  
  410.  
  411.  
  412. /*************************************
  413.  *
  414.  *    Motion object palette
  415.  *
  416.  *************************************/
  417.  
  418. static void mo_color_callback(const UINT16 *data, const struct rectangle *clip, void *param)
  419. {
  420.     const unsigned int *usage = Machine->gfx[1]->pen_usage;
  421.     UINT16 *colormap = param;
  422.     int code = data[1] & 0x7fff;
  423.     int color = data[2] & 0x000f;
  424.     int hsize = ((data[3] >> 4) & 7) + 1;
  425.     int vsize = (data[3] & 7) + 1;
  426.     int tiles = hsize * vsize;
  427.     UINT16 temp = 0;
  428.     int i;
  429.  
  430.     for (i = 0; i < tiles; i++)
  431.         temp |= usage[code++];
  432.     colormap[color] |= temp;
  433. }
  434.  
  435.  
  436.  
  437. /*************************************
  438.  *
  439.  *    Motion object rendering
  440.  *
  441.  *************************************/
  442.  
  443. static void mo_render_callback(const UINT16 *data, const struct rectangle *clip, void *param)
  444. {
  445.     const struct GfxElement *gfx = Machine->gfx[1];
  446.     struct pf_overrender_data overrender_data;
  447.     struct osd_bitmap *bitmap = param;
  448.     struct rectangle pf_clip;
  449.  
  450.     /* extract data from the various words */
  451.     int hflip = data[1] & 0x8000;
  452.     int code = data[1] & 0x7fff;
  453.     int xpos = (data[2] >> 7) - atarigen_video_control_state.sprite_xscroll;
  454.     int color = data[2] & 0x000f;
  455.     int ypos = -(data[3] >> 7) - atarigen_video_control_state.sprite_yscroll;
  456.     int hsize = ((data[3] >> 4) & 7) + 1;
  457.     int vsize = (data[3] & 7) + 1;
  458.  
  459.     /* adjust for height */
  460.     ypos -= vsize * 8;
  461.  
  462.     /* adjust the final coordinates */
  463.     xpos &= 0x1ff;
  464.     ypos &= 0x1ff;
  465.     if (xpos >= XDIM) xpos -= 0x200;
  466.     if (ypos >= YDIM) ypos -= 0x200;
  467.  
  468.     /* determine the bounding box */
  469.     atarigen_mo_compute_clip_8x8(pf_clip, xpos, ypos, hsize, vsize, clip);
  470.  
  471.     /* draw the motion object */
  472.     atarigen_mo_draw_8x8(bitmap, gfx, code, color, hflip, 0, xpos, ypos, hsize, vsize, clip, TRANSPARENCY_PEN, 0);
  473.  
  474.     /* standard priority case? */
  475.     if (color != 15)
  476.     {
  477.         /* overrender the playfield */
  478.         overrender_data.bitmap = bitmap;
  479.         overrender_data.type = OVERRENDER_STANDARD;
  480.         overrender_data.color = color;
  481.         atarigen_pf_process(pf_overrender_callback, &overrender_data, &pf_clip);
  482.     }
  483.  
  484.     /* high priority case? */
  485.     else
  486.     {
  487.         /* overrender the playfield */
  488.         overrender_data.bitmap = atarigen_pf_overrender_bitmap;
  489.         overrender_data.type = OVERRENDER_PRIORITY;
  490.         overrender_data.color = color;
  491.         atarigen_pf_process(pf_overrender_callback, &overrender_data, &pf_clip);
  492.  
  493.         /* finally, copy this chunk to the real bitmap */
  494.         copybitmap(bitmap, atarigen_pf_overrender_bitmap, 0, 0, 0, 0, &pf_clip, TRANSPARENCY_THROUGH, palette_transparent_pen);
  495.     }
  496.  
  497. #if DEBUG_VIDEO
  498.     if (show_colors)
  499.     {
  500.         int tx = (pf_clip.min_x + pf_clip.max_x) / 2 - 3;
  501.         int ty = (pf_clip.min_y + pf_clip.max_y) / 2 - 4;
  502.         drawgfx(bitmap, Machine->uifont, ' ', 0, 0, 0, tx - 2, ty - 2, 0, TRANSPARENCY_NONE, 0);
  503.         drawgfx(bitmap, Machine->uifont, ' ', 0, 0, 0, tx + 2, ty - 2, 0, TRANSPARENCY_NONE, 0);
  504.         drawgfx(bitmap, Machine->uifont, ' ', 0, 0, 0, tx - 2, ty + 2, 0, TRANSPARENCY_NONE, 0);
  505.         drawgfx(bitmap, Machine->uifont, ' ', 0, 0, 0, tx + 2, ty + 2, 0, TRANSPARENCY_NONE, 0);
  506.         drawgfx(bitmap, Machine->uifont, "0123456789ABCDEF"[color], 0, 0, 0, tx, ty, 0, TRANSPARENCY_NONE, 0);
  507.     }
  508. #endif
  509. }
  510.  
  511.  
  512.  
  513. /*************************************
  514.  *
  515.  *    Debugging
  516.  *
  517.  *************************************/
  518.  
  519. #if DEBUG_VIDEO
  520.  
  521. static void mo_print_callback(const UINT16 *data, const struct rectangle *clip, void *param)
  522. {
  523.     FILE *file = param;
  524.  
  525.     /* extract data from the various words */
  526.     int hflip = data[1] & 0x8000;
  527.     int code = data[1] & 0x7fff;
  528.     int xpos = (data[2] >> 7) - 5;
  529.     int color = data[2] & 0x000f;
  530.     int ypos = YDIM - (data[3] >> 7);
  531.     int hsize = ((data[3] >> 4) & 7) + 1;
  532.     int vsize = (data[3] & 7) + 1;
  533.  
  534.     fprintf(file, "P=%04X C=%X F=%X  X=%03X Y=%03X S=%dx%d\n", code, color, hflip >> 15, xpos & 0xfff, ypos & 0xfff, hsize, vsize);
  535. }
  536.  
  537. static void debug(void)
  538. {
  539.     int new_show_colors;
  540.     int new_special;
  541.  
  542.     new_show_colors = keyboard_pressed(KEYCODE_CAPSLOCK);
  543.     if (new_show_colors != show_colors)
  544.     {
  545.         show_colors = new_show_colors;
  546.         memset(atarigen_pf_dirty, 0xff, atarigen_playfieldram_size / 4);
  547.     }
  548.  
  549.     if (keyboard_pressed(KEYCODE_Q)) new_special = 0;
  550.     if (keyboard_pressed(KEYCODE_W)) new_special = 1;
  551.     if (keyboard_pressed(KEYCODE_E)) new_special = 2;
  552.     if (keyboard_pressed(KEYCODE_R)) new_special = 3;
  553.     if (keyboard_pressed(KEYCODE_T)) new_special = 4;
  554.     if (keyboard_pressed(KEYCODE_Y)) new_special = 5;
  555.     if (keyboard_pressed(KEYCODE_U)) new_special = 6;
  556.     if (keyboard_pressed(KEYCODE_I)) new_special = 7;
  557.  
  558.     if (keyboard_pressed(KEYCODE_A)) new_special = 8;
  559.     if (keyboard_pressed(KEYCODE_S)) new_special = 9;
  560.     if (keyboard_pressed(KEYCODE_D)) new_special = 10;
  561.     if (keyboard_pressed(KEYCODE_F)) new_special = 11;
  562.     if (keyboard_pressed(KEYCODE_G)) new_special = 12;
  563.     if (keyboard_pressed(KEYCODE_H)) new_special = 13;
  564.     if (keyboard_pressed(KEYCODE_J)) new_special = 14;
  565.     if (keyboard_pressed(KEYCODE_K)) new_special = 15;
  566.  
  567.     if (keyboard_pressed(KEYCODE_9))
  568.     {
  569.         static int count;
  570.         char name[50];
  571.         FILE *f;
  572.         int i;
  573.  
  574.         while (keyboard_pressed(KEYCODE_9)) { }
  575.  
  576.         sprintf(name, "Dump %d", ++count);
  577.         f = fopen(name, "wt");
  578.  
  579.         fprintf(f, "\n\nMotion Object Palette:\n");
  580.         for (i = 0x000; i < 0x100; i++)
  581.         {
  582.             fprintf(f, "%04X ", READ_WORD(&paletteram[i*2]));
  583.             if ((i & 15) == 15) fprintf(f, "\n");
  584.         }
  585.  
  586.         fprintf(f, "\n\nPlayfield Palette:\n");
  587.         for (i = 0x100; i < 0x200; i++)
  588.         {
  589.             fprintf(f, "%04X ", READ_WORD(&paletteram[i*2]));
  590.             if ((i & 15) == 15) fprintf(f, "\n");
  591.         }
  592.  
  593.         fprintf(f, "\n\nMotion Objects Drawn:\n");
  594.         atarigen_mo_process(mo_print_callback, f);
  595.  
  596.         fprintf(f, "\n\nMotion Objects\n");
  597.         for (i = 0; i < 256; i++)
  598.         {
  599.             UINT16 *data = (UINT16 *)&atarigen_spriteram[i*8];
  600.             int hflip = data[1] & 0x8000;
  601.             int code = data[1] & 0x7fff;
  602.             int xpos = (data[2] >> 7) - 5;
  603.             int ypos = YDIM - (data[3] >> 7);
  604.             int color = data[2] & 0x000f;
  605.             int hsize = ((data[3] >> 4) & 7) + 1;
  606.             int vsize = (data[3] & 7) + 1;
  607.             fprintf(f, "   Object %03X: L=%03X P=%04X C=%X X=%03X Y=%03X W=%d H=%d F=%d LEFT=(%04X %04X %04X %04X)\n",
  608.                     i, data[0] & 0x3ff, code, color, xpos & 0x1ff, ypos & 0x1ff, hsize, vsize, hflip,
  609.                     data[0] & 0xfc00, data[1] & 0x0000, data[2] & 0x0070, data[3] & 0x0008);
  610.         }
  611.  
  612.         fprintf(f, "\n\nPlayfield dump\n");
  613.         for (i = 0; i < atarigen_playfieldram_size / 4; i++)
  614.         {
  615.             fprintf(f, "%X%04X ", READ_WORD(&atarigen_playfieldram[0x2000 + i*2]) >> 8, READ_WORD(&atarigen_playfieldram[i*2]));
  616.             if ((i & 63) == 63) fprintf(f, "\n");
  617.         }
  618.  
  619.         fprintf(f, "\n\nSprite RAM dump\n");
  620.         for (i = 0; i < 0x3000 / 2; i++)
  621.         {
  622.             fprintf(f, "%04X ", READ_WORD(&atarigen_spriteram[i*2]));
  623.             if ((i & 31) == 31) fprintf(f, "\n");
  624.         }
  625.  
  626.         fclose(f);
  627.     }
  628. }
  629.  
  630. #endif
  631.